#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <list>
#include "AbstractGraph.h"



using namespace std;

AbstractGraph::AbstractGraph()
{
}

AbstractGraph::~AbstractGraph()
{
}

AbstractGraph::AbstractGraph(const AbstractGraph &other) :adgencyList(other.getAdjencyList())
{
}

/*AbstractGraph::AbstractGraph(const AbstractGraph &g)
{
  adgencyList =  g.getAdjencyList();
  }*/

void AbstractGraph::addEdge(int vertex, int vertex2) {
  adgencyList[vertex].push_back(vertex2);
  adgencyList[vertex2].push_back(vertex);
}

int AbstractGraph::addVertex() 
{
  adgencyList.push_back(vector<int>());
  return adgencyList.size()-1;
}

int AbstractGraph::addVertex(int vertex) 
{
  adgencyList.push_back(vector<int>(vertex));
  return adgencyList.size()-1;
}

int AbstractGraph::getSize()const
{
  return adgencyList.size();
}

int_vect_vect AbstractGraph::getAdjencyList()const
{
  return adgencyList;
}

vector<int> AbstractGraph::neighbours(int vertex) const
{
  return vector<int>(adgencyList[vertex]);
}

int AbstractGraph::degre(int vertex)const
{
  return adgencyList[vertex].size();
}

void AbstractGraph::delEdgeFromVertex(int vertex) 
{
  vector<int> vect = adgencyList[vertex];
  for (int i = 0; i < vect.size(); i++)
    {
      delEdge(vertex, vect[i]);
    }
}

bool AbstractGraph::isEdge(int vertex1, int vertex2)
{
  for (int i = 0; i < adgencyList[vertex1].size(); i++)
    if (adgencyList[vertex1][i] == vertex2)
      return true;
  return false;
}

void AbstractGraph::delEdge(int vertex1, int vertex2)
{
  vector<int> vect1 = adgencyList[vertex1];
  vector<int> vect2 = adgencyList[vertex2];

  for (int i = 0; i < vect1.size(); i++) 
    {
      if (vect1[i] == vertex2)
	{
	  adgencyList[vertex1].erase(adgencyList[vertex1].begin() + i);
	  break;
	}
    }

  for (int i = 0; i < vect2.size(); i++) 
    {
      if (vect2[i] == vertex1)
	{
	  adgencyList[vertex2].erase(adgencyList[vertex2].begin() + i);
	  break;
	}
    }
}

bool AbstractGraph::hasNoEdge()
{
  for (int i = 0 ; i < getSize(); i++) 
    {
      if (degre(i) > 0)
	return false;
    }
  return true;
}

string AbstractGraph::toString()
{
  std::ostringstream s;
  for (unsigned int i = 0; i < adgencyList.size(); i++) 
    {
      s << i << ":";
      for (unsigned int j = 0; j < adgencyList[i].size(); j++) 
	{
	  s << " " << adgencyList[i][j];
	}
      s << "\n";
    }
  return s.str();
}

void AbstractGraph::printGraph()
{
  cout << "N : " << adgencyList.size()<< endl;
  int_vect_vect::iterator it;
  int cpt = 0;

  for (it = adgencyList.begin (); it != adgencyList.end (); ++it)
    {
      cout << cpt+1 << " : " ;
      vector<int> l = *it;

      for (vector<int>::iterator it2 = l.begin (); it2 != l.end (); ++it2){
	int i = *it2;
	cout << i+1 << " ";
      }
      cout << endl;
      cpt++;
    }
}

void AbstractGraph::readFile(string path)
{
  ifstream fichier(path.c_str(), ios::in);

  if(fichier)
    {
      string ligne;
      int compteur=0;

      while(getline(fichier, ligne))
        {
          vector<int> vect;
          istringstream iss (ligne);
          string sub;
          int cpt =0;
          while (iss >> sub)
	    {
	      if(cpt>0)
		{ 
		  vect.push_back(atoi(sub.c_str()));
		}
	      cpt++;
	    }
          if(compteur !=0)
            adgencyList.push_back (vect);
          compteur++;
        }
      fichier.close();
    }
  else
    cerr << "Impossible d'ouvrir le fichier !" << endl;
}

void AbstractGraph::writeFile(string path)
{
  ofstream fichier(path.c_str(), ios::out | ios::trunc);

  if(fichier)
    {
      int_vect_vect::iterator it;
      int cpt = 0;
      fichier << "N: " <<adgencyList.size() << endl;
      for (it = adgencyList.begin(); it != adgencyList.end(); ++it)
	{
	  fichier << cpt << ": " ;
	  vector<int> l = *it;

	  for (vector<int>::iterator it2 = l.begin(); it2 != l.end(); ++it2)
	    {
	      int i = *it2;
	      fichier << i << " ";
	    }
	  fichier << endl;
	  cpt++;
	}
      fichier.close();
    }
  else
    cerr << "Erreur à l'ouverture !" << endl;
}

vector<int> AbstractGraph::operator[](int i)const
{
 return neighbours(i); 
}

std::ostream& operator<<(std::ostream &os,const AbstractGraph& g)
{
  return os;
}

